package com.harmony.pilot.knowledge.controller;

import com.harmony.pilot.knowledge.service.CallChainService;
import com.harmony.pilot.knowledge.service.CallChainService.CallChainResult;
import com.harmony.pilot.knowledge.service.CallChainService.CallerInfo;
import com.harmony.pilot.knowledge.service.CallChainService.CrossRepoCallInfo;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 调用链分析Controller
 */
@RestController
@RequestMapping("/api/knowledge/callchain")
@RequiredArgsConstructor
public class CallChainController {
    
    private final CallChainService callChainService;
    
    /**
     * 查询函数调用链（支持任意深度）
     * 
     * GET /api/knowledge/callchain?from=MethodA&to=MethodZ&maxDepth=50
     * 
     * 参数说明：
     * - from: 起始函数名
     * - to: 目标函数名
     * - maxDepth: 最大搜索深度（默认10，支持1-999）
     * 
     * 深度建议：
     * - 1-10层: 快速查询
     * - 11-20层: 正常查询
     * - 21-50层: 深度查询（建议使用Neo4j）
     * - 50+层: 超深查询（必须使用Neo4j）
     * 
     * 示例响应：
     * {
     *   "chains": [
     *     {
     *       "path": ["MethodA", "MethodB", "MethodC", "MethodD", ..., "MethodZ"],
     *       "depth": 25,
     *       "crossRepoCount": 3,
     *       "hasCircular": false
     *     }
     *   ],
     *   "totalFound": 5,
     *   "searchDepth": 50,
     *   "queryTimeMs": 1230
     * }
     */
    @GetMapping
    public ResponseEntity<CallChainResponse> getCallChain(
            @RequestParam String from,
            @RequestParam String to,
            @RequestParam(defaultValue = "10") int maxDepth,
            @RequestParam(defaultValue = "100") int maxResults) {
        
        long startTime = System.currentTimeMillis();
        
        // 参数校验
        if (maxDepth < 1 || maxDepth > 999) {
            throw new IllegalArgumentException("maxDepth必须在1-999之间");
        }
        
        List<CallChainResult> chains = callChainService.findCallChain(from, to, maxDepth);
        
        // 限制结果数量
        if (chains.size() > maxResults) {
            chains = chains.subList(0, maxResults);
        }
        
        CallChainResponse response = new CallChainResponse();
        response.setChains(chains);
        response.setTotalFound(chains.size());
        response.setSearchDepth(maxDepth);
        response.setQueryTimeMs(System.currentTimeMillis() - startTime);
        
        return ResponseEntity.ok(response);
    }
    
    /**
     * 查询函数的所有调用者（反向查询）
     * 
     * GET /api/knowledge/callchain/callers/MethodD?depth=5
     * 
     * 示例响应：
     * {
     *   "callers": [
     *     {
     *       "name": "MethodC",
     *       "depth": 1,
     *       "direct": true,
     *       "file": "c.cpp",
     *       "repo": "foundation/arkui"
     *     },
     *     {
     *       "name": "MethodB",
     *       "depth": 2,
     *       "direct": false
     *     }
     *   ]
     * }
     */
    @GetMapping("/callers/{functionName}")
    public ResponseEntity<List<CallerInfo>> getCallers(
            @PathVariable String functionName,
            @RequestParam(defaultValue = "5") int depth) {
        
        List<CallerInfo> callers = callChainService.findCallers(functionName, depth);
        return ResponseEntity.ok(callers);
    }
    
    /**
     * 查询跨仓调用
     * 
     * GET /api/knowledge/callchain/cross-repo?repo=foundation/arkui
     * 
     * 示例响应：
     * {
     *   "crossRepoCalls": [
     *     {
     *       "callerName": "MethodC",
     *       "callerRepo": "foundation/arkui",
     *       "calleeName": "MethodD",
     *       "calleeRepo": "commonlibrary/c_utils",
     *       "isInnerAPI": true,
     *       "declaredIn": "inner_api.h"
     *     }
     *   ]
     * }
     */
    @GetMapping("/cross-repo")
    public ResponseEntity<List<CrossRepoCallInfo>> getCrossRepoCalls(
            @RequestParam String repo) {
        
        List<CrossRepoCallInfo> calls = callChainService.findCrossRepoCalls(repo);
        return ResponseEntity.ok(calls);
    }
    
    /**
     * 查询所有调用inner API的地方
     * 
     * GET /api/knowledge/callchain/inner-api-usage
     */
    @GetMapping("/inner-api-usage")
    public ResponseEntity<List<CrossRepoCallInfo>> getInnerAPIUsage() {
        // 查询所有跨仓且调用inner API的关系
        // TODO: 实现具体逻辑
        return ResponseEntity.ok(List.of());
    }
    
    /**
     * 查询从某个函数出发所有可达的函数
     * 
     * GET /api/knowledge/callchain/reachable/MethodA?maxDepth=20
     */
    @GetMapping("/reachable/{functionName}")
    public ResponseEntity<ReachableResponse> getReachableFunctions(
            @PathVariable String functionName,
            @RequestParam(defaultValue = "15") int maxDepth) {
        
        // TODO: 实现可达性分析
        return ResponseEntity.ok(new ReachableResponse());
    }
    
    /**
     * 查询最短路径
     * 
     * GET /api/knowledge/callchain/shortest?from=A&to=Z
     */
    @GetMapping("/shortest")
    public ResponseEntity<CallChainResult> getShortestPath(
            @RequestParam String from,
            @RequestParam String to) {
        
        // BFS自然返回最短路径
        List<CallChainResult> chains = callChainService.findCallChain(from, to, 50);
        
        if (chains.isEmpty()) {
            return ResponseEntity.notFound().build();
        }
        
        // 返回深度最小的路径
        CallChainResult shortest = chains.stream()
            .min(Comparator.comparingInt(CallChainResult::getDepth))
            .orElse(chains.get(0));
        
        return ResponseEntity.ok(shortest);
    }
    
    // 响应DTO
    @lombok.Data
    public static class CallChainResponse {
        private List<CallChainResult> chains;
        private int totalFound;
        private int searchDepth;
        private long queryTimeMs;
    }
    
    @lombok.Data
    public static class ReachableResponse {
        private List<ReachableFunction> reachable;
        private int totalCount;
    }
    
    @lombok.Data
    public static class ReachableFunction {
        private String name;
        private int depth;
        private String file;
        private String repo;
    }
}

